// ts语法巩固

// 1、定义id类型为字符串或者数字
let id:string | number = 1;
id = 'abc1234'

// 2、数组
// 写法一
let arr:number[] = [1,2,3,4,5,6]
let arr2:string[] = ['1','ba', '21']
let arr3:(string|number)[] = [1,2,3,4,5,'6', 'fadf']
let arr4:any[] = ['1','ba', 21, true]

// 写法二
let arr5:Array<number> = [1,2,3,4,5,6]
let arr6:Array<string> = ['1','ba', '21']
let arr7:Array<string|number> = ['1','ba', 1]
let arr8:Array<any> = ['1','ba', 21, true]

// 3、对象类型的定义
let o1 = {
    id:1,
    age:12,
    name:'张三'
}
// 在面向对象语言中，接口（interface）是一个重要的概念，它是对行为的抽象
// 接口（Interface）可以用于对[对象的形状（shape）进行描述，类似与Java中的接口
// 注意：一旦定义任意属性，那么确定属性和可选属性都必须是它的子属性
interface Person {// 只做规范和约束，不做具体实现
    name:string;// 确定属性
    age:number;
    grade?:string; // 可选属性
    [propName:string]:any //任意属性，可添加任意多个
}

let Tom:Person = {
    age:16,
    name:'小黑',
    msg:'abc', // 任意属性
    // 任意属性
    action: function () {
        return 'abc'
    }
}

let Tom2:Person = {
    age:16,
    name:'小狗',
    grade:'3年级',
    userid:111 // 任意属性
}

// 4、函数function 输入类型   输出类型
function add(n1:number = 0, n2:number = 0):number {
    return n1 + n2
}
add(1, 2)

function add2(n1:number, n2:number):void {
    console.log(n1, n2)
}
add2(1, 2)

// 5、泛型：是指在定义函数，接口或类的时候，不预先指定具体的类型，而在使用的时候再指定类型的一种特性
function fn<E>(n1:E, n2:E):E[] {
    return [n1, n2];
}
fn(1,3)
fn('hell', ' world')

// 泛型约束
interface ILength {
    length:number;
}
function f1<E extends ILength>(n1:E):number {
    return n1.length;
}
f1('hello world')
// 扩展题
interface IEqual {
    <T>(a:T, b:T):boolean;
}
// 定义一个函数，判断传入的参数是否一样
// function f2(s1:number, s2:number):boolean {
//     return s1 === s2
// }
let f2:IEqual = (a, b) => a === b;
f2<string>('a', 'b')
// let f2: IEqual = function (a, b) {
//     return a === b;
// }
// f2(2, 2)

// 定义一个函数，判断参数大小
function f3(a:number, b:number):boolean {
    return a > b ? true : false;
}

interface IEqual2<T> {
    (a:T, b:T):boolean;
}

let f4:IEqual2<string> = (a, b) => a === b;
f4('a', 'b')